home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-09-15 | 54.9 KB | 2,080 lines |
- Newsgroups: comp.sources.misc
- X-UNIX-From: ssbell!sparky!kent
- subject: v14i082: lc - Categorize and List Files In Columns, Part 1 of 2
- from: kent@sparky.IMD.Sterling.COM (Kent Landfield)
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 14, Issue 82
- Submitted-by: kent@sparky.IMD.Sterling.COM (Kent Landfield)
- Archive-name: lc/part01
-
- [It's decidedly difficult to gain access to one's uunet mailbox when one's
- Internet access denies all knowledge of uunet. One could wish OS upgrades
- went faster than taking an entire week. ++bsa]
-
- [Xenix warning: this conflicts with /bin/lc. I suggest a rename. ++bsa]
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # If this archive is complete, you will see the following message at the end:
- # "End of archive 1 (of 2)."
- # Contents: README MANIFEST lc.c lc.mk qsort.c
- # Wrapped by kent@sparky on Fri Sep 7 16:10:04 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(4940 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X
- X LC
- X
- X "@(#)README 1.3 9/7/90 Kent Landfield"
- X
- XThis directory contains the source to lc. lc is much like the ls
- Xcommand except it separates the types of files into groups and then
- Xdisplays located file names to the user is a columnar fashion.
- X
- Xlc was initially implemented by myself after I became accustomed
- Xto the lc command on a Mark Williams Coherent system I was running back
- Xin 1984. When I started moving to different systems I found that I did
- Xnot like the lack of information, flexibility and the general display
- Xthat ls provided. I have found that I am not the only one that has
- Xbecome feed up with ls and its jumbled output. All the people here use
- Xlc much more than they use ls. It is a locally well known fact that when
- Xa new machine comes into the house, the first local software that is put
- Xon the machine is lc. It is far from perfect but it is better than ls on
- Xa general use basis.
- X
- Xlc uses three different environment variables COLS, CDPATH, and LC
- Xallowing you to customize how you wish lc to perform on a default
- Xbasis. COLS is used to switch the column width between 80 and 132
- Xcolumn display. LC is used to set lc specific options. The command
- Xline options shown in the option list below are available to be used
- Xin setting up how lc is to work for you. Options that you supply on
- Xthe command line override options that are specified in the environment.
- Xlc uses CDPATH to locate files that are requested but are not in the
- Xspecified location or within the local directory.
- X
- Xlc has incorporated minimal spell checking using slightly modified
- Xroutines found in the book, The UNIX Programming Environment, by
- XBrian Kernighan and Rob Pike.
- X
- XThe following is a quick reference of options to lc. These options
- Xcan be specified in the Environment variable LC so that they are
- Xdone each time lc is executed.
- X
- X lc -- categorize files in a directory and list column-wise
- X
- X Usage: lc [ options ] [ directory ... ]
- X
- X Options:
- X -a List dot files as well.
- X -b List block special files only
- X -c List character special files only
- X -d List directories only
- X -D Do not display singular files
- X -e Mark executable files with '*'
- X -f List regular files only
- X -F List fifo files only
- X -1 List files one per line instead of in columns
- X -r Do not sort the file names before displaying.
- X -m List shared memory name space entry files only
- X -M List semaphore name space entry files only
- X -S List socket file only
- X -s List symbolic links only
- X -L Display symbolic links
- X -l Mark symbolic links with '@'
- X -I Suppress unresolved symbolic link messages.
- X
- X The "only" options can not be combined.
- X
- X If there is no 'directory' specified, the current directory is used.
- X
- X Not all options are supported on every system. (e.g. no symbolic links
- X on your system ? Options -s, -L or -l won't be available..)
- X If your system does not support shared memory name space entry files,
- X then you cannot use the -m option...
- X
- XHistory:
- X Initially designed on an IBM-XT running Coherent in 1984.
- X Ported to XENIX on an IBM-AT in 1984.
- X Ported to System V on AT&T 3Bs in 1985.
- X Ported to DEC Vax 11/750 running System V in 1986.
- X Ported to BSD4.2 on a Sequent Balance 8000 in 1986.
- X Jeff Minnig added the initial support for links.
- X Ported to SunOS 4.0 on a Sun 3/60 in 1988.
- X Rick Ohnemus did major surgery to remove static storage
- X and *greatly* enhanced the link support. Thanks rick!
- X Tested with Ultrix 3.0 & 3.1 on a DECstation 3100 in 1989.
- X Tested with Ultrix 3.0 & 3.1 on a VAXstation 3500 in 1989.
- X Ported to AIX 2.2 on an IBM RT.
- X Tested with UTek on a Tektronix 4319 in 1989.
- X Tested with IRIX System V on a Silicon Graphics Iris 4D/210GTX in 1989.
- X Tested with AmigaDOS 1.3 on an Amiga 1000 in 1989.
- X Tested with SunOS 4.0.3 on a Sparkstation 1 in 1989.
- X Tested with UTek on a Tektronix XD8810 in 1989.
- X Tested with AIX 3.+ on a Risc System/6000 in 1990.
- X
- XThe following is a todo list that may get done someday...
- X
- X1. Port to all flavors of unix on all platforms. Lofty goal but
- X on-going... :-)
- X2. Need to modify lc so that one environment (or compile) option will
- X only let you see files you own or have access to.
- X3. Add spell checking code to CDPATH usage
- X4. Allow combination of only options...
- X
- X *PLEASE!*
- XIf you have a problem, there's someone else out there who either has
- Xhad or will have the same problem. Please send all "lc" ideas, patches,
- Xetc to
- X
- XINTERNET: kent@sparky.IMD.Sterling.COM or UUCP: uunet!ssbell!sparky!kent
- X
- Xso that I can continue to improve the functionality and portability of lc.
- X
- X -Kent+
- X
- X
- END_OF_FILE
- if test 4940 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(442 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- X File Name Archive # Description
- X----------------------------------------------------------
- X README 1 General information file.
- X MANIFEST 1 This shipping list
- X lc.1 2 lc manual page in nroff format.
- X lc.c 1 Source to the lc command.
- X lc.mk 1 Makefile for the lc command.
- X qsort.c 1 BSD libc.a qsort source (optional)
- END_OF_FILE
- if test 442 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- if test -f 'lc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'lc.c'\"
- else
- echo shar: Extracting \"'lc.c'\" \(35879 characters\)
- sed "s/^X//" >'lc.c' <<'END_OF_FILE'
- X/*
- X** This software is
- X**
- X** Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 by Kent Landfield.
- X**
- X** Permission is hereby granted to copy, distribute or otherwise
- X** use any part of this package as long as you do not try to make
- X** money from it or pretend that you wrote it. This copyright
- X** notice must be maintained in any copy made.
- X**
- X** Use of this software constitutes acceptance for use in an AS IS
- X** condition. There are NO warranties with regard to this software.
- X** In no event shall the author be liable for any damages whatsoever
- X** arising out of or in connection with the use or performance of this
- X** software. Any use of this software is at the user's own risk.
- X**
- X** If you make modifications to this software that you feel
- X** increases it usefulness for the rest of the community, please
- X** email the changes, enhancements, bug fixes as well as any and
- X** all ideas to me. Thanks!
- X**
- X** Kent Landfield
- X** kent@sparky.IMD.Sterling.COM
- X** sparky!kent
- X**
- X** Subsystem: lc - List Columnwise/Categories
- X**
- X** Abstract : lc -- categorize files in a directory and list columnwize
- X**
- X** Usage: lc [ options ] [ directory ... ]
- X**
- X** Options:
- X** -a List dot files as well.
- X** -b List block special files only
- X** -c List character special files only
- X** -d List directories only
- X** -D Do not display singular files
- X** -e Mark executable files with '*'
- X** -f List regular files only
- X** -F List fifo files only
- X** -1 List files one per line instead of in columns
- X** -r Do not sort the filenames before displaying.
- X** -m List shared memory name space entry files only
- X** -M List semaphore name space entry files only
- X** -S List socket file only
- X** -s List symbolic links only
- X** -L Display symbolic links
- X** -l Mark symbolic links with '@'
- X** -I Suppress unresolved symbolic link messages.
- X**
- X** The "only" options can not be combined.
- X** If there is no 'directory' specified, the current directory is used.
- X** Not all options are supported on every system. (e.g. no symbolic links
- X** on your system ? Options -s, -L or -l won't be available..)
- X**
- X** History:
- X** Initially designed on an IBM-XT running Coherent in 1984.
- X** Ported to XENIX on an IBM-AT in 1984.
- X** Ported to System V on AT&T 3Bs in 1985.
- X** Ported to DEC Vax 11/750 running System V in 1986.
- X** Ported to BSD4.2 on a Sequent Balance 8000 in 1986.
- X** Jeff Minnig added the initial support for links.
- X** Ported to SunOS 4.0 on a Sun 3/60 in 1988.
- X** Rick Ohnemus did major surgery to remove static storage
- X** and *greatly* enhanced the link support. Thanks rick!
- X** Tested with Ultrix 3.0 & 3.1 on a DECstation 3100 in 1989.
- X** Tested with Ultrix 3.0 & 3.1 on a VAXstation 3500 in 1989.
- X** Tested with UTek on a Tektronix 4319 in 1989.
- X** Tested with IRIX System V on a Silicon Graphics Iris 4D/210GTX in 1989.
- X** Tested with AmigaDOS 1.3 on an Amiga 1000 in 1989.
- X** Tested with SunOS 4.0.3 on a Sparkstation 1 in 1989.
- X** Tested with AIX 3.+ on a Risc System/6000 in 1990.
- X**
- X*/
- X#ifndef lint
- Xstatic char *sccsid = "@(#)lc.c 1.23 9/7/90 Kent Landfield";
- X#endif
- X
- X#include <stdio.h>
- X#ifdef BSD
- X# include <strings.h>
- X# include <sys/param.h>
- X#else
- X# include <string.h>
- X# include <sys/types.h>
- X#endif
- X#include <sys/stat.h>
- X#ifdef POSIX
- X# include <limits.h>
- X# include <dirent.h>
- X#else
- X# ifdef BSD
- X# ifdef DIRECT
- X# include <sys/dir.h>
- X# else
- X# include <dirent.h>
- X# endif
- X# else
- X# include <sys/dir.h>
- X# endif
- X#endif
- X
- X#ifndef NAME_MAX
- X# ifdef BSD
- X# define NAME_MAX MAXNAMLEN
- X# else
- X# ifdef DIRSIZ
- X# define NAME_MAX DIRSIZ
- X# else
- X# define NAME_MAX 14
- X# endif
- X# endif
- X#endif
- X
- X#ifndef PATH_MAX
- X# ifdef MAXPATHLEN
- X# define PATH_MAX MAXPATHLEN
- X# else
- X# ifdef MAXNAMLEN
- X# define PATH_MAX MAXNAMLEN
- X# else
- X# define PATH_MAX 255
- X# endif
- X# endif
- X#endif
- X
- X#define BUFSIZE PATH_MAX
- X
- X#define NODES_PER_HUNK 256
- X
- X#define TRUE 1
- X#define FALSE 0
- X
- X#ifndef S_IXUSR
- X# define S_IXUSR S_IEXEC
- X#endif
- X
- X#ifndef S_IXGRP
- X# define S_IXGRP (S_IEXEC >> 3)
- X#endif
- X
- X#ifndef S_IXOTH
- X# define S_IXOTH (S_IEXEC >> 6)
- X#endif
- X
- X#define DIR_ONLY 1
- X#define FILE_ONLY 2
- X#ifdef S_IFCHR
- X# define CHAR_ONLY 3
- X#endif
- X#ifdef S_IFBLK
- X# define BLOCK_ONLY 4
- X#endif
- X#ifdef S_IFIFO
- X# define FIFO_ONLY 5
- X#endif
- X#ifdef S_IFLNK
- X# define LNK_ONLY 6
- X#endif
- X#ifdef S_IFSOCK
- X# define SOCK_ONLY 7
- X#endif
- X#ifdef S_IFNAM
- X# define SEM_ONLY 8
- X# define SD_ONLY 9
- X#endif
- X
- X#ifdef BSD
- X# define strrchr rindex
- X# define strchr index
- X#endif
- X
- X
- Xstruct list {
- X int num;
- X int max;
- X char **names;
- X#ifdef LENS
- X int maxlen;
- X#endif
- X};
- X
- X#ifdef LENS
- X
- X#ifdef S_IFBLK
- Xstruct list Blks = { 0, 0, (char **) NULL, 0 };
- X#endif
- X
- X#ifdef S_IFCHR
- Xstruct list Chrs = { 0, 0, (char **) NULL, 0 };
- X#endif
- X
- Xstruct list Dirs = { 0, 0, (char **) NULL, 0 };
- Xstruct list Fls = { 0, 0, (char **) NULL, 0 };
- X
- X#ifdef S_IFIFO
- Xstruct list Fifos = { 0, 0, (char **) NULL, 0 };
- X#endif
- X
- X#ifdef S_IFLNK
- Xstruct list Lnks = { 0, 0, (char **) NULL, 0 };
- Xstruct list Lnksn = { 0, 0, (char **) NULL, 0 };
- X#endif
- X
- X#ifdef S_IFSOCK
- Xstruct list Socks = { 0, 0, (char **) NULL, 0 };
- X#endif
- X
- X#ifdef S_IFNAM
- Xstruct list Sds = { 0, 0, (char **) NULL, 0 };
- Xstruct list Sems = { 0, 0, (char **) NULL, 0 };
- X#endif
- X
- X#else /* ifndef LENS */
- X
- X#ifdef S_IFBLK
- Xstruct list Blks = { 0, 0, (char **) NULL };
- X#endif
- X
- X#ifdef S_IFCHR
- Xstruct list Chrs = { 0, 0, (char **) NULL };
- X#endif
- X
- Xstruct list Dirs = { 0, 0, (char **) NULL };
- Xstruct list Fls = { 0, 0, (char **) NULL };
- X
- X#ifdef S_IFIFO
- Xstruct list Fifos = { 0, 0, (char **) NULL };
- X#endif
- X
- X#ifdef S_IFLNK
- Xstruct list Lnks = { 0, 0, (char **) NULL };
- Xstruct list Lnksn = { 0, 0, (char **) NULL };
- X#endif
- X
- X#ifdef S_IFSOCK
- Xstruct list Socks = { 0, 0, (char **) NULL };
- X#endif
- X
- X#ifdef S_IFNAM
- Xstruct list Sds = { 0, 0, (char **) NULL };
- Xstruct list Sems = { 0, 0, (char **) NULL };
- X#endif
- X
- X#endif /* LENS */
- X
- Xchar *Progname;
- X
- Xint Allfiles = FALSE;
- Xint Display_single = TRUE;
- Xint Executables = FALSE;
- Xint Ignore = FALSE;
- Xint Level = 0;
- Xint Maxlen = 0;
- Xint Only = FALSE;
- Xint Screen_width = 80;
- Xint Single = FALSE;
- Xint Sort_wanted = TRUE;
- X
- X#ifdef S_IFLNK
- Xint Current = 0;
- Xint Disp_links = FALSE;
- Xint Mark_links = FALSE;
- Xint lstat();
- Xint readlink();
- X#endif
- X
- X#ifndef _BSD
- X# ifdef BSD
- X extern char *sprintf();
- X extern int exit();
- X extern int free();
- X extern int qsort();
- X# else
- X extern int sprintf();
- X extern void exit();
- X extern void free();
- X extern void qsort();
- X# endif
- X extern int fprintf();
- X extern int printf();
- X extern int sscanf();
- X#endif
- X
- Xvoid lc();
- X
- Xextern char *getenv();
- Xextern char *malloc();
- Xextern char *realloc();
- Xextern int access();
- Xextern int fputs();
- Xextern int puts();
- Xextern int stat();
- X
- X/* S T R _ S A V
- X *
- X * str_sav() returns a pointer to a new string which is a dupli-
- X * cate of the string pointed to by s. The space for the new
- X * string is obtained using malloc(3). If the new string can-
- X * not be created, the process prints an error message on stderr
- X * and terminates.
- X */
- X
- Xchar *str_sav(s)
- X char *s;
- X{
- X char *p;
- X
- X if ((p = malloc((unsigned)(strlen(s) + 1))) == (char *) NULL) {
- X (void) fprintf(stderr, "%s: malloc: out of memory\n", Progname);
- X exit(1);
- X }
- X (void) strcpy(p, s);
- X return (p);
- X}
- X
- X/* D I R E C T O R Y
- X *
- X * directory() is used to open and read the directory and pass
- X * the filenames found to the routine lc();
- X */
- X#if (POSIX || BSD)
- Xvoid directory(dname)
- X char *dname;
- X{
- X register char *nbp;
- X register char *nep;
- X DIR *dstream;
- X int i;
- X#ifdef DIRECT
- X struct direct *dp;
- X#else
- X struct dirent *dp;
- X#endif
- X
- X /* add a slash to the end of the directory name */
- X nbp = dname + strlen(dname);
- X#ifdef AMIGA
- X if (*(nbp - 1) != ':') {
- X *nbp++ = '/';
- X *nbp = '\0';
- X }
- X#else
- X *nbp++ = '/';
- X *nbp = '\0';
- X#endif
- X
- X if ((dstream = opendir(dname)) == NULL) {
- X (void) fprintf(stderr, "%s: can't open %s\n", Progname, dname);
- X return;
- X }
- X
- X while ((dp = readdir(dstream)) != NULL) {
- X if (strcmp(dp->d_name, ".") == 0
- X || strcmp(dp->d_name, "..") == 0
- X || (!Allfiles && *(dp->d_name) == '.'))
- X continue;
- X
- X for (i = 0, nep = nbp; dp->d_name[i] && i < NAME_MAX; i++)
- X *nep++ = dp->d_name[i];
- X *nep++ = '\0';
- X lc(dname, 2);
- X }
- X (void) closedir(dstream);
- X *--nbp = '\0';
- X return;
- X}
- X
- X#else /* not POSIX or BSD */
- X
- X/* D I R E C T O R Y
- X *
- X * directory() is used to open and read the directory and pass
- X * the filenames found to the routine lc();
- X */
- Xvoid directory(dname)
- X char *dname;
- X{
- X register char *nbp;
- X register char *nep;
- X FILE *fd;
- X int i;
- X struct direct dir;
- X
- X /* add a slash to the end of the directory name */
- X nbp = dname + strlen(dname);
- X *nbp++ = '/';
- X *nbp = '\0';
- X
- X if ((nbp + NAME_MAX + 2) >= (dname + BUFSIZE)) { /* dname too long */
- X (void) fprintf(stderr, "%s: dirname too long: %s\n",
- X Progname, dname);
- X return;
- X }
- X
- X if ((fd = fopen(dname, "r")) == (FILE *) NULL) { /* open the directory */
- X (void) fprintf(stderr, "%s: can't open %s\n", Progname, dname);
- X return;
- X }
- X
- X while (fread((char *) &dir, sizeof(dir), 1, fd) > 0) {
- X if (dir.d_ino == 0
- X || strcmp(dir.d_name, ".") == 0
- X || strcmp(dir.d_name, "..") == 0)
- X continue;
- X for (i = 0, nep = nbp; i < NAME_MAX; i++)
- X *nep++ = dir.d_name[i];
- X *nep++ = '\0';
- X lc(dname, 2);
- X }
- X (void) fclose(fd);
- X *--nbp = '\0'; /* restore dname */
- X return;
- X}
- X#endif
- X
- X/* G E T L I N K
- X *
- X * getlink() calls readlink() which places the contents of the
- X * symbolic link referred to by fn in the buffer wk. The contents
- X * of the link are null terminated and the path is returned to
- X * the calling funtion as a pointer to a storage area created
- X * by using malloc(3);
- X */
- X
- X#ifdef S_IFLNK
- Xchar *getlink(fn)
- X char *fn;
- X{
- X char wk[PATH_MAX + 1];
- X int rc;
- X
- X rc = readlink(fn, wk, sizeof(wk));
- X if (rc < 0)
- X return ((char *) NULL);
- X wk[rc] = '\0';
- X return (str_sav(wk));
- X}
- X#endif
- X
- X/* P R I N T _ L I N E
- X *
- X * print_line() is used to format and output the files previously
- X * located. This routine could use a lot more smarts but currently
- X * it is rather crude...
- X */
- X
- Xint print_line(files, ind)
- X struct list *files;
- X int ind;
- X{
- X register char *frmt;
- X char out_str[PATH_MAX + 3];
- X int i;
- X int prt_limit;
- X
- X if (Single) {
- X#ifdef S_IFLNK
- X if (Current == LNK_ONLY) {
- X if (*(Lnksn.names + ind) != (char *) NULL)
- X (void) printf(" %s -> %s\n",
- X *(Lnks.names + ind), *(Lnksn.names + ind));
- X else
- X (void) printf(" %s -> %s\n",
- X *(Lnks.names + ind), "UNRESOLVED");
- X ind++;
- X return (ind);
- X }
- X#endif
- X (void) puts(*(files->names + ind));
- X ind++;
- X }
- X else if (Maxlen > ((Screen_width - 4) / 2)) {
- X (void) printf(" %s\n", *(files->names + ind));
- X ind++;
- X }
- X else {
- X frmt = out_str;
- X for (i = 0; i < 4; i++)
- X *frmt++ = ' ';
- X
- X /* The prt_limit may need to be smarter */
- X
- X prt_limit = (Screen_width - 4) / (Maxlen + 1);
- X if (Maxlen == 3 || Maxlen == 1)
- X prt_limit--;
- X
- X while ((ind < files->num) && (prt_limit-- > 0)) {
- X i = 0;
- X do {
- X if (*(*(files->names + ind) + i) == '\0') {
- X while (i++ <= Maxlen)
- X *frmt++ = ' ';
- X }
- X else
- X *frmt++ = *(*(files->names + ind) + i);
- X i++;
- X } while (i <= Maxlen);
- X ind++;
- X }
- X *frmt = '\0';
- X (void) puts(out_str);
- X }
- X return (ind);
- X}
- X
- X/* S T R _ C M P
- X *
- X * str_cmp is the comparison routine used by
- X * qsort(3) to order the filenames inplace.
- X */
- X
- Xint str_cmp(s1, s2)
- X char **s1;
- X char **s2;
- X{
- X return strcmp(*s1, *s2);
- X}
- X
- X/* P R _ I N F O
- X *
- X * pr_info() is used to sort the data if required
- X * and then pass it to print_line to actually output
- X * the data.`
- X */
- X
- Xint pr_info(strng, files, flg, sort_needed)
- X char *strng;
- X struct list *files;
- X int flg;
- X int sort_needed;
- X{
- X int pnum = 0;
- X
- X#ifdef LENS
- X Maxlen = files->maxlen;
- X#endif
- X
- X#ifdef S_IFLNK
- X if (!Single || Current == LNK_ONLY) {
- X if (flg)
- X (void) puts("");
- X (void) puts(strng);
- X }
- X#else
- X if (!Single) {
- X if (flg)
- X (void) puts("");
- X (void) puts(strng);
- X }
- X#endif
- X
- X if (sort_needed)
- X qsort((char *) (files->names), files->num,
- X sizeof(char *), str_cmp);
- X
- X do {
- X pnum = print_line(files, pnum);
- X } while (pnum < files->num);
- X
- X return (1);
- X}
- X
- X/* P R I N T _ I N F O
- X *
- X * print_info() is called to display all the filenames
- X * located in the directory reading and storage functions.
- X */
- X
- Xvoid print_info()
- X{
- X int flag = 0;
- X
- X#ifdef S_IFLNK
- X int ssing;
- X
- X Current = 0;
- X
- X if (Lnks.num > 0 && (Disp_links == TRUE || Only == LNK_ONLY)) {
- X ssing = Single;
- X Single = TRUE;
- X Current = LNK_ONLY;
- X flag = pr_info("Symbolic Links: ", &Lnks, flag, 0);
- X Single = ssing;
- X }
- X#endif
- X
- X#ifdef S_IFSOCK
- X if (Socks.num > 0 && (Only == 0 || Only == SOCK_ONLY))
- X flag = pr_info("Sockets: ", &Socks, flag, Sort_wanted);
- X#endif
- X
- X#ifdef S_IFNAM
- X if (Sems.num > 0 && (Only == 0 || Only == SEM_ONLY))
- X flag = pr_info("Semaphore Files: ", &Sems, flag, Sort_wanted);
- X
- X if (Sds.num > 0 && (Only == 0 || Only == SD_ONLY))
- X flag = pr_info("Shared Data Files: ", &Sds, flag, Sort_wanted);
- X#endif
- X
- X#ifdef S_IFIFO
- X if (Fifos.num > 0 && (Only == 0 || Only == FIFO_ONLY))
- X flag = pr_info("Fifo Files: ", &Fifos, flag, Sort_wanted);
- X#endif
- X
- X#ifdef S_IFCHR
- X if (Chrs.num > 0 && (Only == 0 || Only == CHAR_ONLY))
- X flag = pr_info("Character Special Files: ", &Chrs, flag, Sort_wanted);
- X#endif
- X
- X#ifdef S_IFBLK
- X if (Blks.num > 0 && (Only == 0 || Only == BLOCK_ONLY))
- X flag = pr_info("Block Special Files: ", &Blks, flag, Sort_wanted);
- X#endif
- X
- X if (Dirs.num > 0 && (Only == 0 || Only == DIR_ONLY))
- X flag = pr_info("Directories: ", &Dirs, flag, Sort_wanted);
- X
- X if (Fls.num > 0 && (Only == 0 || Only == FILE_ONLY))
- X flag = pr_info("Files: ", &Fls, flag, Sort_wanted);
- X
- X return;
- X}
- X
- X/* B A S E N A M E
- X *
- X * basename() is used to return the base file name of a
- X * path refered to by name. The base file name is stored
- X * into a storage location refered to by str. It is the
- X * calling function's responsibility to assure adequate
- X * storage is supplied.
- X */
- X
- Xvoid basename(name, str)
- X char *name;
- X char *str;
- X{
- X char *p;
- X
- X if ((p = strrchr(name, '/')) == (char *) NULL) {
- X#ifdef AMIGA
- X if ((p = strchr(name, ':')) == (char *) NULL)
- X (void) strcpy(str, name);
- X else
- X (void) strcpy(str, ++p);
- X#else
- X (void) strcpy(str, name);
- X#endif
- X }
- X else
- X (void) strcpy(str, ++p);
- X return;
- X}
- X
- X/* A D D _ T O _ L I S T
- X *
- X * add_to_list() is used to add the supplied filename refered to
- X * by str to the appropriate category storage array.
- X */
- X
- Xvoid add_to_list(files, str)
- X struct list *files;
- X char *str;
- X{
- X if (files->max == 0) {
- X files->names = (char **) malloc(sizeof(char *) * NODES_PER_HUNK);
- X if (files->names == (char **) NULL) {
- X (void) fprintf(stderr,
- X "%s: malloc: out of memory\n", Progname);
- X exit(1);
- X }
- X files->max = NODES_PER_HUNK;
- X }
- X else if (files->num == files->max) {
- X files->names =
- X (char **) realloc((char *) files->names,
- X (unsigned) sizeof(char *)
- X * (files->max + NODES_PER_HUNK));
- X if (files->names == (char **) NULL) {
- X (void) fprintf(stderr,
- X "%s: realloc: out of memory\n", Progname);
- X exit(1);
- X }
- X files->max += NODES_PER_HUNK;
- X }
- X if (str == (char *) NULL)
- X *(files->names + files->num++) = (char *) NULL;
- X else
- X *(files->names + files->num++) = str_sav(str);
- X return;
- X}
- X
- X/* L C
- X *
- X * lc() is main function for determining the type of
- X * the file refered to by name.
- X */
- X
- Xvoid lc(name, cnt)
- X char *name;
- X int cnt;
- X{
- X#ifdef S_IFLNK
- X char *link;
- X#endif
- X char sav_str[BUFSIZE + 2];
- X int mlen;
- X struct stat sbuf;
- X
- X#ifdef S_IFLNK
- X if (lstat(name, &sbuf) < 0) {
- X (void) fprintf(stderr, "%s: can't stat %s\n", Progname, name);
- X return;
- X }
- X#else
- X if (stat(name, &sbuf) == -1) {
- X (void) fprintf(stderr, "%s: can't stat %s\n", Progname, name);
- X return;
- X }
- X#endif
- X
- X basename(name, sav_str);
- X mlen = strlen(sav_str);
- X
- X#ifndef LENS
- X if (mlen > Maxlen)
- X Maxlen = mlen;
- X#endif
- X
- X switch (sbuf.st_mode & S_IFMT) {
- X
- X case S_IFDIR:
- X if (!Allfiles && sav_str[0] == '.' && Level != 0)
- X break;
- X if (cnt != 1) /* dont store the dir name on entry */
- X add_to_list(&Dirs, sav_str);
- X /* never called - left for expansion to recursive */
- X /* searches of subdirectories. Right, re-write needed */
- X /* in output facilities first... */
- X if (Level++ == 0)
- X directory(name);
- X#ifdef LENS
- X if (mlen > Dirs.maxlen)
- X Dirs.maxlen = mlen;
- X#endif
- X break;
- X
- X case S_IFREG:
- X /* do not print .files unless enviromental variable */
- X /* or option set. */
- X if (!Allfiles && sav_str[0] == '.')
- X break;
- X if (Executables
- X && (sbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
- X *(sav_str + mlen) = '*';
- X ++mlen;
- X *(sav_str + mlen) = '\0';
- X#ifndef LENS
- X if (mlen > Maxlen)
- X Maxlen = mlen;
- X#endif
- X }
- X add_to_list(&Fls, sav_str);
- X#ifdef LENS
- X if (mlen > Fls.maxlen)
- X Fls.maxlen = mlen;
- X#endif
- X break;
- X
- X#ifdef S_IFCHR
- X case S_IFCHR:
- X if (!Allfiles && sav_str[0] == '.')
- X break;
- X add_to_list(&Chrs, sav_str);
- X#ifdef LENS
- X if (mlen > Chrs.maxlen)
- X Chrs.maxlen = mlen;
- X#endif
- X break;
- X#endif
- X
- X#ifdef S_IFBLK
- X case S_IFBLK:
- X if (!Allfiles && sav_str[0] == '.')
- X break;
- X add_to_list(&Blks, sav_str);
- X#ifdef LENS
- X if (mlen > Blks.maxlen)
- X Blks.maxlen = mlen;
- X#endif
- X break;
- X#endif
- X
- X#ifdef S_IFIFO
- X case S_IFIFO:
- X if (!Allfiles && sav_str[0] == '.')
- X break;
- X add_to_list(&Fifos, sav_str);
- X#ifdef LENS
- X if (mlen > Fifos.maxlen)
- X Fifos.maxlen = mlen;
- X#endif
- X break;
- X#endif
- X
- X#ifdef S_IFLNK
- X case S_IFLNK:
- X if (!Allfiles && sav_str[0] == '.')
- X break;
- X add_to_list(&Lnks, sav_str);
- X link = getlink(name);
- X add_to_list(&Lnksn, link);
- X if (link != (char *) NULL)
- X free(link);
- X#ifdef LENS
- X if (mlen > Lnks.maxlen)
- X Lnks.maxlen = mlen;
- X#endif
- X if (stat(name, &sbuf) < 0) {
- X if (!Ignore)
- X (void) fprintf(stderr,
- X "%s: %s: can't resolve symbolic link\n",
- X Progname, name);
- X }
- X else {
- X if (Mark_links) {
- X *(sav_str + mlen) = '@';
- X ++mlen;
- X *(sav_str + mlen) = '\0';
- X#ifndef LENS
- X if (mlen > Maxlen)
- X Maxlen = mlen;
- X#endif
- X }
- X
- X switch (sbuf.st_mode & S_IFMT) {
- X
- X case S_IFDIR:
- X if (cnt != 1) /*dont store the dir name on entry */
- X add_to_list(&Dirs, sav_str);
- X /* never called - left for expansion to recursive */
- X /* searches of subdirectories */
- X if (Level++ == 0)
- X directory(name);
- X#ifdef LENS
- X if (mlen > Dirs.maxlen)
- X Dirs.maxlen = mlen;
- X#endif
- X break;
- X
- X case S_IFREG:
- X if (Executables
- X && (sbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
- X *(sav_str + mlen) = '*';
- X ++mlen;
- X *(sav_str + mlen) = '\0';
- X#ifndef LENS
- X if (mlen > Maxlen)
- X Maxlen = mlen;
- X#endif
- X }
- X add_to_list(&Fls, sav_str);
- X#ifdef LENS
- X if (mlen > Fls.maxlen)
- X Fls.maxlen = mlen;
- X#endif
- X break;
- X
- X#ifdef S_IFCHR
- X case S_IFCHR:
- X add_to_list(&Chrs, sav_str);
- X#ifdef LENS
- X if (mlen > Chrs.maxlen)
- X Chrs.maxlen = mlen;
- X#endif
- X break;
- X#endif
- X
- X#ifdef S_IFBLK
- X case S_IFBLK:
- X add_to_list(&Blks, sav_str);
- X#ifdef LENS
- X if (mlen > Blks.maxlen)
- X Blks.maxlen = mlen;
- X#endif
- X break;
- X#endif
- X
- X#ifdef S_IFIFO
- X case S_IFIFO:
- X add_to_list(&Fifos, sav_str);
- X#ifdef LENS
- X if (mlen > Fifos.maxlen)
- X Fifos.maxlen = mlen;
- X#endif
- X break;
- X#endif
- X
- X#ifdef S_IFSOCK
- X case S_IFSOCK :
- X add_to_list(&Socks, sav_str);
- X#ifdef LENS
- X if (mlen > Socks.maxlen)
- X Socks.maxlen = mlen;
- X#endif
- X break;
- X#endif
- X }
- X }
- X break;
- X#endif
- X
- X#ifdef S_IFSOCK
- X case S_IFSOCK:
- X if (!Allfiles && sav_str[0] == '.')
- X break;
- X add_to_list(&Socks, sav_str);
- X#ifdef LENS
- X if (mlen > Socks.maxlen)
- X Socks.maxlen = mlen;
- X#endif
- X break;
- X#endif
- X
- X#ifdef S_IFNAM
- X case S_IFNAM:
- X switch (sbuf.st_rdev) {
- X
- X case S_INSEM:
- X if (!Allfiles && sav_str[0] == '.')
- X break;
- X add_to_list(&Sems, sav_str);
- X#ifdef LENS
- X if (mlen > Sems.maxlen)
- X Sems.maxlen = mlen;
- X#endif
- X break;
- X
- X case S_INSHD:
- X if (!Allfiles && sav_str[0] == '.')
- X break;
- X add_to_list(&Sds, sav_str);
- X#ifdef LENS
- X if (mlen > Sds.maxlen)
- X Sds.maxlen = mlen;
- X#endif
- X break;
- X }
- X break;
- X#endif
- X
- X }
- X return;
- X}
- X
- X/* V A L I D _ O P T
- X *
- X * valid_opt() is used to translate user has supplied option
- X * letters into something that this process can use. It sets
- X * up the options and if a usage is requested, it sets up and
- X * prints a usage message for the user.
- X */
- X
- Xvoid valid_opt(c, usage)
- X char c;
- X int usage;
- X{
- X char up[7];
- X
- X up[0] = '\0';
- X
- X switch(c) {
- X
- X case 'a':
- X Allfiles = TRUE;
- X break;
- X
- X case 'b':
- X Only = BLOCK_ONLY;
- X break;
- X
- X case 'c':
- X Only = CHAR_ONLY;
- X break;
- X
- X case 'd':
- X Only = DIR_ONLY;
- X break;
- X
- X case 'D':
- X Display_single = FALSE;
- X break;
- X
- X case 'e':
- X Executables = TRUE;
- X break;
- X
- X case 'f':
- X Only = FILE_ONLY;
- X break;
- X
- X case 'r':
- X Sort_wanted = FALSE;
- X break;
- X
- X#ifdef S_IFIFO
- X case 'F':
- X Only = FIFO_ONLY;
- X break;
- X#endif
- X
- X case '1':
- X Single = TRUE;
- X break;
- X
- X#ifdef S_IFLNK
- X case 's':
- X Only = LNK_ONLY;
- X break;
- X
- X case 'l':
- X Mark_links = TRUE;
- X break;
- X
- X case 'I':
- X Ignore = TRUE;
- X break;
- X
- X case 'L':
- X Disp_links = TRUE;
- X break;
- X#endif
- X
- X#ifdef S_IFSOCK
- X case 'S':
- X Only = SOCK_ONLY;
- X break;
- X#endif
- X
- X#ifdef S_IFNAM
- X case 'm':
- X Only = SD_ONLY;
- X break;
- X
- X case 'M':
- X Only = SEM_ONLY;
- X break;
- X#endif
- X
- X default:
- X if (usage == TRUE) {
- X#ifdef S_IFLNK
- X (void) strcat(up, "IlLs");
- X#endif
- X#ifdef S_IFSOCK
- X (void) strcat(up, "S");
- X#endif
- X#ifdef S_IFNAM
- X (void) strcat(up, "mM");
- X#endif
- X (void) fprintf(stderr,
- X "usage: %s [-abcdDefF1%s] [directories or files]\n",
- X Progname, up);
- X exit(1);
- X }
- X }
- X
- X return;
- X}
- X
- X/* S E T _ E N V _ V A R S
- X *
- X * set_env_vars() is used get the environment variables that
- X * lc uses. The environment variable LC can be used to setup
- X * the default way in which the user likes to see a directory
- X * listing. Command line options override those specified in
- X * the environment.
- X */
- X
- Xvoid set_env_vars()
- X{
- X char *ep;
- X
- X if ((ep = getenv("COLS")) != (char *) NULL) {
- X if (sscanf(ep, "%d", &Screen_width) == 0
- X || (Screen_width != 80 && Screen_width != 132))
- X Screen_width = 80;
- X }
- X
- X if ((ep = getenv("LC")) != (char *) NULL) {
- X while (*ep != '\0') {
- X valid_opt(*ep, FALSE);
- X ep++;
- X }
- X }
- X
- X return;
- X}
- X
- X/* S P D I S T: return the distance between two names
- X *
- X * very rough spelling metric:
- X * 0 if the strings are identical
- X * 1 if two chars are transposed
- X * 2 if 1 char wrong, added or deleted
- X * 3 otherwise
- X */
- X#define EQ(s, t) (strcmp(s, t) == 0)
- X
- Xint spdist(s, t)
- X char *s;
- X char *t;
- X{
- X while (*s++ == *t) {
- X if (*t++ == '\0')
- X return 0; /* exact match */
- X }
- X if (*--s) {
- X if (*t) {
- X if (s[1] && t[1] && *s == t[1] && *t == s[1] && EQ(s+2, t+2))
- X return 1; /* transposition */
- X if (EQ(s+1, t+1))
- X return 2; /* 1 char mismatch */
- X }
- X if (EQ(s+1, t))
- X return 2; /* extra chacter */
- X }
- X if (*t && EQ(s, t+1))
- X return 2; /* missing character */
- X return 3;
- X}
- X
- X/* M I N D I S T
- X *
- X * mindist() searches the directory for the best guess
- X * in the event the requested file was not located.
- X */
- X
- X#if (POSIX || BSD)
- Xint mindist(dir, guess, best) /* set best, return distance 0..3 */
- X char *dir;
- X char *guess;
- X char *best;
- X{
- X DIR *dfd;
- X int d;
- X int nd;
- X#ifdef DIRECT
- X struct direct *dp;
- X#else
- X struct dirent *dp;
- X#endif
- X
- X if (dir[0] == '\0')
- X dir = ".";
- X d = 3; /* minimum distance */
- X
- X if ((dfd = opendir(dir)) == NULL)
- X return d;
- X
- X while ((dp = readdir(dfd)) != NULL) {
- X if (dp->d_ino) {
- X nd = spdist(dp->d_name, guess);
- X if (nd <= d && nd != 3) {
- X (void) strcpy(best, dp->d_name);
- X d = nd;
- X if (d == 0) /* exact match */
- X break;
- X }
- X }
- X }
- X (void) closedir(dfd);
- X return d;
- X}
- X
- X#else /* not POSIX or BSD */
- X
- X/* M I N D I S T
- X *
- X * mindist() searches the directory for the best guess
- X * in the event the requested file was not located.
- X */
- X
- Xint mindist(dir, guess, best) /* set best, return distance 0..3 */
- X char *dir;
- X char *guess;
- X char *best;
- X{
- X FILE *fd;
- X int d;
- X int nd;
- X struct {
- X ino_t ino;
- X char name[NAME_MAX + 1]; /* 1 more than in dir.h */
- X } nbuf;
- X
- X nbuf.name[NAME_MAX] = '\0'; /* +1 for terminal '\0' */
- X if (dir[0] == '\0')
- X dir = ".";
- X d = 3; /* minimum distance */
- X if ((fd = fopen(dir, "r")) == (FILE *) NULL)
- X return d;
- X while (fread((char *) &nbuf, sizeof(struct direct), 1, fd) > 0) {
- X if (nbuf.ino) {
- X nd = spdist(nbuf.name, guess);
- X if (nd <= d && nd != 3) {
- X (void) strcpy(best, nbuf.name);
- X d = nd;
- X if (d == 0) /* exact match */
- X break;
- X }
- X }
- X }
- X (void) fclose(fd);
- X return d;
- X}
- X#endif
- X
- X/* S P N A M E: return correctly spelled filename
- X *
- X * spname(oldname, newname) char *oldname, *newname;
- X * returns -1 if no reasonable match to oldname,
- X * 0 if exact match,
- X * 1 if corrected.
- X * stores corrected name in newname.
- X */
- X
- Xint spname(oldname, newname)
- X char *oldname;
- X char *newname;
- X{
- X char *new = newname;
- X char *old = oldname;
- X char *p;
- X char best[NAME_MAX + 1];
- X char guess[NAME_MAX + 1];
- X
- X for (;;) {
- X while (*old == '/') /* skip slashes */
- X *new++ = *old++;
- X *new = '\0';
- X if (*old == '\0') /* exact or corrected */
- X return (strcmp(oldname, newname) != 0);
- X p = guess; /* copy next component into guess */
- X for (/* void */ ; *old != '/' && *old != '\0'; old++) {
- X if (p < (guess + NAME_MAX))
- X *p++ = *old;
- X }
- X *p = '\0';
- X if (mindist(newname, guess, best) >= 3)
- X return (-1); /* hopeless */
- X for (p = best; *new = *p++; new++) /* add to end */
- X /* void */;
- X }
- X}
- X
- X/* I N _ C D P A T H
- X *
- X * in_cdpath() searches the CDPATH stored in the environment
- X * for the filename specified. If it is found, fill the
- X * storage area refered to by buffer with the corrected path.
- X * Return TRUE if located and FALSE if not located in the CDPATH.
- X */
- X
- Xint in_cdpath(requested_dir, buffer)
- X char *requested_dir;
- X char *buffer;
- X{
- X static char *cdpath;
- X static int first = 1;
- X
- X char *cp;
- X char *path;
- X char patbuf[BUFSIZE + 1];
- X int quit;
- X
- X if (first) {
- X if ((cdpath = getenv("CDPATH")) != (char *) NULL)
- X cdpath = str_sav(cdpath);
- X first = 0;
- X }
- X
- X if (cdpath == (char *) NULL)
- X return (0);
- X
- X (void) strcpy(patbuf, cdpath);
- X path = patbuf;
- X
- X quit = 0;
- X
- X while (!quit) {
- X cp = strchr(path, ':');
- X if (cp == (char *) NULL)
- X quit++;
- X else
- X *cp = '\0';
- X
- X if (*(path + 1) == '\0' && *path == '/')
- X (void) sprintf(buffer, "/%s", requested_dir);
- X else
- X (void) sprintf(buffer, "%s/%s",
- X (*path ? path : "."), requested_dir);
- X
- X if (access(buffer, 1) == 0)
- X return (TRUE);
- X path = ++cp;
- X }
- X return (FALSE);
- X}
- X
- X/* M A I N
- X *
- X * Ye olde main();
- X */
- X
- Xint main(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X char *argp;
- X#ifdef S_IFLNK
- X char *link;
- X#endif
- X char buf[BUFSIZE + 1];
- X int idx;
- X int nl;
- X struct stat sbuf;
- X
- X nl = idx = FALSE;
- X
- X Progname = argv[0];
- X
- X set_env_vars(); /* get environment variables */
- X
- X /* All command line arguments must be */
- X /* lumped together such as `lc -aef` */
- X
- X if (argc > 1 && argv[1][0] == '-') { /* if first parm is command */
- X argp = argv[1];
- X
- X while (*(++argp))
- X valid_opt(*argp, TRUE);
- X
- X ++argv;
- X --argc;
- X }
- X
- X /*
- X ** The user has not specified a file or directory
- X ** to be examined so assume that the current directory
- X ** is what the user is requesting.
- X */
- X if (argc == 1) {
- X (void) strcpy(buf, ".");
- X lc(buf, 1);
- X print_info();
- X return(0);
- X }
- X
- X /*
- X ** The user has specified at least one file or
- X ** directory to be examined.
- X */
- X if (argc > 2)
- X nl = TRUE;
- X while (--argc > 0) {
- X ++argv;
- X (void) strcpy(buf, *argv);
- Xskipit:
- X if (stat(buf, &sbuf) == -1) {
- X if (in_cdpath(*argv, buf) || (spname(*argv, buf) != -1)) {
- X /*
- X ** Check to see if the requested is in the CDPATH
- X ** and if not try to correct for typos. Always print
- X ** the name of what was found...
- X */
- X nl = TRUE;
- X goto skipit;
- X }
- X else
- X (void)fprintf(stderr, "%s: can't find %s\n",
- X Progname, *argv);
- X }
- X else {
- X switch (sbuf.st_mode & S_IFMT) {
- X
- X case S_IFREG:
- X if (Display_single)
- X (void) printf("%s: file\n", buf);
- X break;
- X
- X#ifdef S_IFCHR
- X case S_IFCHR:
- X if (Display_single)
- X (void) printf("%s: character special file\n", buf);
- X break;
- X#endif
- X
- X#ifdef S_IFBLK
- X case S_IFBLK:
- X if (Display_single)
- X (void) printf("%s: block special file\n", buf);
- X break;
- X#endif
- X
- X#ifdef S_IFIFO
- X case S_IFIFO:
- X if (Display_single)
- X (void) printf("%s: fifo file\n", buf);
- X break;
- X#endif
- X
- X#ifdef S_IFSOCK
- X case S_IFSOCK:
- X if (Display_single)
- X (void) printf("%s: socket file\n", buf);
- X break;
- X#endif
- X
- X#ifdef S_IFLNK
- X case S_IFLNK:
- X if (Display_single) {
- X if ((link = getlink(buf)) != (char *) NULL) {
- X (void) printf("%s: symbolic link to %s\n",
- X buf, link);
- X free(link);
- X }
- X else
- X (void) printf("%s: unresolved symbolic link\n",
- X buf);
- X }
- X break;
- X#endif
- X
- X#ifdef S_IFNAM
- X case S_IFNAM:
- X if (Display_single) {
- X if (sbuf.st_rdev == S_INSHD)
- X (void) printf("%s: shared memory file\n", buf);
- X if (sbuf.st_rdev == S_INSEM)
- X (void) printf("%s: semaphore file\n", buf);
- X }
- X break;
- X#endif
- X
- X case S_IFDIR:
- X Maxlen = Level = 0;
- X#ifdef S_IFBLK
- X Blks.num = 0;
- X#ifdef LENS
- X Blks.maxlen = 0;
- X#endif
- X#endif
- X
- X#ifdef S_IFCHR
- X Chrs.num = 0;
- X#ifdef LENS
- X Chrs.maxlen = 0;
- X#endif
- X#endif
- X
- X Dirs.num = Fls.num = 0;
- X#ifdef LENS
- X Dirs.maxlen = Fls.maxlen = 0;
- X#endif
- X
- X#ifdef S_IFIFO
- X Fifos.num = 0;
- X#ifdef LENS
- X Fifos.maxlen = 0;
- X#endif
- X#endif
- X
- X#ifdef S_IFLNK
- X Lnks.num = Lnksn.num = 0;
- X#ifdef LENS
- X Lnks.maxlen = Lnksn.maxlen = 0;
- X#endif
- X#endif
- X
- X#ifdef S_IFSOCK
- X Socks.num = 0;
- X#ifdef LENS
- X Socks.maxlen = 0;
- X#endif
- X#endif
- X
- X#ifdef S_IFNAM
- X Sds.num = Sems.num = 0;
- X#ifdef LENS
- X Sds.maxlen = Sems.maxlen = 0;
- X#endif
- X#endif
- X
- X if (nl == TRUE) {
- X if (idx > 0)
- X (void) puts("");
- X else
- X ++idx;
- X (void) fputs(": ", stdout);
- X (void) fputs(buf, stdout);
- X (void) puts(" :");
- X }
- X lc(buf, 1);
- X print_info();
- X break;
- X
- X default:
- X (void) printf("%s: unknown file type\n", buf);
- X break;
- X }
- X }
- X }
- X return(0);
- X}
- END_OF_FILE
- if test 35879 -ne `wc -c <'lc.c'`; then
- echo shar: \"'lc.c'\" unpacked with wrong size!
- fi
- # end of 'lc.c'
- fi
- if test -f 'lc.mk' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'lc.mk'\"
- else
- echo shar: Extracting \"'lc.mk'\" \(3469 characters\)
- sed "s/^X//" >'lc.mk' <<'END_OF_FILE'
- X#
- X# "@(#)lc.mk 1.6 9/7/90 - Kent Landfield (c) 1984,1985,1986,1987,1988,1989,1990
- X#
- X# This makefile is used to compile lc.
- X#
- X# Initially designed on an IBM-XT running Coherent in 1984.
- X# Ported to XENIX on an IBM-AT in 1984.
- X# Ported to System V on AT&T 3Bs in 1985.
- X# Ported to DEC Vax 11/750 running System V in 1986.
- X# Ported to BSD4.2 on a Sequent Balance 8000 in 1986.
- X# Jeff Minnig added the initial support for links.
- X# Ported to SunOS 4.0 on a Sun 3/60 in 1988.
- X# Rick Ohnemus did major surgery to remove static storage
- X# and *greatly* enhanced the link support. Thanks rick!
- X# Tested with Ultrix 3.0 & 3.1 on a DECstation 3100 in 1989.
- X# Tested with Ultrix 3.0 & 3.1 on a VAXstation 3500 in 1989.
- X# Ported to AIX 2.2 on an IBM RT.
- X# Tested with UTek on a Tektronix 4319 in 1989.
- X# Tested with IRIX System V on a Silicon Graphics Iris 4D/210GTX in 1989.
- X# Tested with AmigaDOS 1.3 on an Amiga 1000 in 1989.
- X# Tested with SunOS 4.0.3 on a Sparkstation 1 in 1989.
- X# Tested with UTek on a Tektronix XD8810 in 1989.
- X# Runs on AIX 3.+ on a Risc System/6000 in 1990.
- X#
- XI = /usr/include
- XS = $(I)/sys
- X#
- X# Have a favorite C compiler that is not cc... Too bad. ;-)
- XCC=cc
- X#CC=gcc
- X#
- X# If you are running on a BSD 4.2 box:
- X# (note - if compiling on a sequent in att environment...`ucb make -f lc.mk`)
- X# FLAGS = -DBSD -DDIRECT
- X# or
- X#
- X# If you are running on a BSD (4.3 or later), SunOS (4.0 or later),
- X# or Ultrix (3.0 or later) box:
- XFLAGS = -DBSD
- X# or
- X#
- X# If you are running on an Ultrix box and using the POSIX environment:
- X# FLAGS = -DPOSIX
- X# or
- X#
- X# If you are running on a Xenix box:
- X# FLAGS = -DXENIX
- X# or
- X#
- X# If you are running System V or AIX 2.2:
- X# FLAGS =
- X# or
- X#
- X# This runs on AIX but it does not lint well due to the include
- X# files on AIX. It works, that's all I can say...
- X# If you are running AIX 3.0 or later:
- X# FLAGS = -D_BSD -DBSD
- X# or
- X#
- X# If you are running System V with Doug Gwyn's directory routines
- X# or Silicon Graphics or Utek 3.2d:
- X# FLAGS = -DPOSIX
- X#
- X#
- X# OPTIM is used for setting debugging or optimizing
- X# flags for the compilation.
- X#OPTIM=-O -Wall
- XOPTIM=-O
- X
- X# Are the directory routines in another library ?
- X# Or do you wish to use shared libraries ?
- X# Add additional libraries here...
- X# LDFLAGS = -lndir
- X# LDFLAGS = -lc_s
- XLDFLAGS =
- X#
- X# 'qsort' function in C library
- X# QSORTO =
- X# QSORTC =
- X#
- X# 'qsort' function not in C library Or Your qsort library
- X# function is slooow.
- X#
- X# QSORTO = qsort.o
- X# QSORTC = qsort.c
- X#
- X# Installation ownership and directory. Customize
- X# for your installation. Warning, if you do not
- X# install this on your root partition, it will
- X# not be available for use in single user mode.
- X# Yes I know that this last statement is obvious
- X# but it is extremely irritating not to have it
- X# available...
- X#
- X# This is one program that we use so often, that we have set
- X# the sticky bit on (chmod +t lc) on our older systems were
- X# it matters...
- X#
- XBINDIR=/bin
- XMODE=755
- XOWNER=bin
- XGROUP=bin
- X
- XCFLAGS = $(OPTIM) $(FLAGS)
- XOBJS = lc.o $(QSORTO)
- X
- Xlc: lc.o $(QSORTO)
- X $(CC) $(CFLAGS) lc.o $(QSORTO) -o lc $(LDFLAGS)
- X
- Xlint:
- X lint $(FLAGS) $(QSORTC) lc.c
- X
- Xclean:
- X rm -f $(OBJS)
- X
- Xclobber: clean
- X rm -f lc
- X
- Xinstall: lc
- X strip lc
- X cp lc $(BINDIR)/lc
- X chmod $(MODE) $(BINDIR)/lc
- X chown $(OWNER) $(BINDIR)/lc
- X chgrp $(GROUP) $(BINDIR)/lc
- END_OF_FILE
- if test 3469 -ne `wc -c <'lc.mk'`; then
- echo shar: \"'lc.mk'\" unpacked with wrong size!
- fi
- # end of 'lc.mk'
- fi
- if test -f 'qsort.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'qsort.c'\"
- else
- echo shar: Extracting \"'qsort.c'\" \(6230 characters\)
- sed "s/^X//" >'qsort.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1980 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Berkeley. The name of the
- X * University may not be used to endorse or promote products derived
- X * from this software without specific prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X */
- X
- X#if !defined(lint)
- Xstatic char sccsid[] = "@(#)qsort.c 5.4 (Berkeley) 6/27/88";
- X#endif /* LIBC_SCCS and not lint */
- X
- X/*
- X * qsort.c:
- X * Our own version of the system qsort routine which is faster by an average
- X * of 25%, with lows and highs of 10% and 50%.
- X * The THRESHold below is the insertion sort threshold, and has been adjusted
- X * for records of size 48 bytes.
- X * The MTHREShold is where we stop finding a better median.
- X */
- X
- X#define THRESH 4 /* threshold for insertion */
- X#define MTHRESH 6 /* threshold for median */
- X
- Xstatic int (*qcmp)(); /* the comparison routine */
- Xstatic int qsz; /* size of each record */
- Xstatic int thresh; /* THRESHold in chars */
- Xstatic int mthresh; /* MTHRESHold in chars */
- X
- X/*
- X * qst:
- X * Do a quicksort
- X * First, find the median element, and put that one in the first place as the
- X * discriminator. (This "median" is just the median of the first, last and
- X * middle elements). (Using this median instead of the first element is a big
- X * win). Then, the usual partitioning/swapping, followed by moving the
- X * discriminator into the right place. Then, figure out the sizes of the two
- X * partions, do the smaller one recursively and the larger one via a repeat of
- X * this code. Stopping when there are less than THRESH elements in a partition
- X * and cleaning up with an insertion sort (in our caller) is a huge win.
- X * All data swaps are done in-line, which is space-losing but time-saving.
- X * (And there are only three places where this is done).
- X */
- X
- Xstatic void
- Xqst(base, max)
- X char *base, *max;
- X{
- X register char c, *i, *j, *jj;
- X register int ii;
- X char *mid, *tmp;
- X int lo, hi;
- X
- X /*
- X * At the top here, lo is the number of characters of elements in the
- X * current partition. (Which should be max - base).
- X * Find the median of the first, last, and middle element and make
- X * that the middle element. Set j to largest of first and middle.
- X * If max is larger than that guy, then it's that guy, else compare
- X * max with loser of first and take larger. Things are set up to
- X * prefer the middle, then the first in case of ties.
- X */
- X lo = max - base; /* number of elements as chars */
- X do {
- X mid = i = base + qsz * ((lo / qsz) >> 1);
- X if (lo >= mthresh) {
- X j = (qcmp((jj = base), i) > 0 ? jj : i);
- X if (qcmp(j, (tmp = max - qsz)) > 0) {
- X /* switch to first loser */
- X j = (j == jj ? i : jj);
- X if (qcmp(j, tmp) < 0)
- X j = tmp;
- X }
- X if (j != i) {
- X ii = qsz;
- X do {
- X c = *i;
- X *i++ = *j;
- X *j++ = c;
- X } while (--ii);
- X }
- X }
- X /*
- X * Semi-standard quicksort partitioning/swapping
- X */
- X for (i = base, j = max - qsz; ; ) {
- X while (i < mid && qcmp(i, mid) <= 0)
- X i += qsz;
- X while (j > mid) {
- X if (qcmp(mid, j) <= 0) {
- X j -= qsz;
- X continue;
- X }
- X tmp = i + qsz; /* value of i after swap */
- X if (i == mid) {
- X /* j <-> mid, new mid is j */
- X mid = jj = j;
- X } else {
- X /* i <-> j */
- X jj = j;
- X j -= qsz;
- X }
- X goto swap;
- X }
- X if (i == mid) {
- X break;
- X } else {
- X /* i <-> mid, new mid is i */
- X jj = mid;
- X tmp = mid = i; /* value of i after swap */
- X j -= qsz;
- X }
- X swap:
- X ii = qsz;
- X do {
- X c = *i;
- X *i++ = *jj;
- X *jj++ = c;
- X } while (--ii);
- X i = tmp;
- X }
- X /*
- X * Look at sizes of the two partitions, do the smaller
- X * one first by recursion, then do the larger one by
- X * making sure lo is its size, base and max are update
- X * correctly, and branching back. But only repeat
- X * (recursively or by branching) if the partition is
- X * of at least size THRESH.
- X */
- X i = (j = mid) + qsz;
- X if ((lo = j - base) <= (hi = max - i)) {
- X if (lo >= thresh)
- X qst(base, j);
- X base = i;
- X lo = hi;
- X } else {
- X if (hi >= thresh)
- X qst(i, max);
- X max = j;
- X }
- X } while (lo >= thresh);
- X return;
- X}
- X
- X/*
- X * qsort:
- X * First, set up some global parameters for qst to share. Then, quicksort
- X * with qst(), and then a cleanup insertion sort ourselves. Sound simple?
- X * It's not...
- X */
- X
- Xvoid
- Xqsort(base, n, size, compar)
- X char *base;
- X int n;
- X int size;
- X int (*compar)();
- X{
- X register char c, *i, *j, *lo, *hi;
- X char *min, *max;
- X
- X if (n <= 1)
- X return;
- X qsz = size;
- X qcmp = compar;
- X thresh = qsz * THRESH;
- X mthresh = qsz * MTHRESH;
- X max = base + n * qsz;
- X if (n >= THRESH) {
- X qst(base, max);
- X hi = base + thresh;
- X } else {
- X hi = max;
- X }
- X /*
- X * First put smallest element, which must be in the first THRESH, in
- X * the first position as a sentinel. This is done just by searching
- X * the first THRESH elements (or the first n if n < THRESH), finding
- X * the min, and swapping it into the first position.
- X */
- X for (j = lo = base; (lo += qsz) < hi; )
- X if (qcmp(j, lo) > 0)
- X j = lo;
- X if (j != base) {
- X /* swap j into place */
- X for (i = base, hi = base + qsz; i < hi; ) {
- X c = *j;
- X *j++ = *i;
- X *i++ = c;
- X }
- X }
- X /*
- X * With our sentinel in place, we now run the following hyper-fast
- X * insertion sort. For each remaining element, min, from [1] to [n-1],
- X * set hi to the index of the element AFTER which this one goes.
- X * Then, do the standard insertion sort shift on a character at a time
- X * basis for each element in the frob.
- X */
- X for (min = base; (hi = min += qsz) < max; ) {
- X while (qcmp(hi -= qsz, min) > 0)
- X /* void */;
- X if ((hi += qsz) != min) {
- X for (lo = min + qsz; --lo >= min; ) {
- X c = *lo;
- X for (i = j = lo; (j -= qsz) >= hi; i = j)
- X *i = *j;
- X *i = c;
- X }
- X }
- X }
- X return;
- X}
- END_OF_FILE
- if test 6230 -ne `wc -c <'qsort.c'`; then
- echo shar: \"'qsort.c'\" unpacked with wrong size!
- fi
- # end of 'qsort.c'
- fi
- echo shar: End of archive 1 \(of 2\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-